package common

import (
	"bytes"
	"net"
	"strings"
)

type SpiderStats struct {
	*SpiderContext
	Crawled   int
	Successed int
	Failed    int
}

func NewStats(context *SpiderContext) *SpiderStats {
	return &SpiderStats{SpiderContext: context}
}
func (self *SpiderStats) Server() {
	go startServer(_DEFAULT_STATS_SERVER_ADDR, self)
}
func (self SpiderStats) Report() []byte {
	var status = make(map[string]int)
	status["crawled pages"] = self.Crawled
	status["successed"] = self.Successed
	status["failed"] = self.Failed
	return bytes.Join([][]byte{[]byte("spider reports:"),
		JsonDump(status), []byte("\r\n")}, []byte("\r\n"))
}

func startServer(addr string, stats *SpiderStats) {
	netAddr, err := net.ResolveTCPAddr("tcp", addr)
	if err != nil {
		logger.Error(err)
		return
	}
	listener, err := net.Listen("tcp", netAddr.String())
	if err != nil {
		logger.Error(err)
		return
	}
	logger.Info("stats server listening on port %d", netAddr.Port)
	defer listener.Close()
	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Error(err)
			continue
		}
		go handleClient(conn, stats)
	}
}
func handleClient(conn net.Conn, stats *SpiderStats) {

	read_data := make([]byte, 1024)
	defer conn.Close()
	send(conn, []byte("\r\nwelcome to the spider engine."))
	send(conn, []byte("\r\nspider>"))
	for {
		read_len, err := conn.Read(read_data)
		if err != nil {
			logger.Error(err)
			break
		}
		if read_len == 0 {
			logger.Debug("client has been closed.")
			break
		} else {
			command := string(read_data[:read_len])
			switch strings.TrimSpace(command) {
			case "stats":
				send(conn, stats.Report())
				send(conn, []byte("\r\nspider>"))
			case "help":
				send(conn, []byte(usage()))
				send(conn, []byte("\r\nspider>"))
			case "close":
				stats.SpiderContext.SpiderClose <- true
			default:
				send(conn, []byte("unkonwn command,<help> show command lists.\r\n"))
				send(conn, []byte("\r\nspider>"))
			}

		}
	}
}
func usage() string {

	return "\r\n" +
		"commands:\n" +
		"help 	show usage.\n" +
		"stats 	show spider stats\n" +
		"close 	close the spider.\n"
}
func send(conn net.Conn, b []byte) {
	conn.Write(b)
}
